// Generated from crn.g4 by ANTLR 4.1

package odesimulation;

import java.util.HashMap;

import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.runtime.tree.*;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;

@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class crnParser extends Parser {
	protected static final DFA[] _decisionToDFA;
	protected static final PredictionContextCache _sharedContextCache =
		new PredictionContextCache();
	public static final int
		T__16=1, T__15=2, T__14=3, T__13=4, T__12=5, T__11=6, T__10=7, T__9=8, 
		T__8=9, T__7=10, T__6=11, T__5=12, T__4=13, T__3=14, T__2=15, T__1=16, 
		T__0=17, ID=18, ENZYME=19, NUM=20, VALUE=21, COMMENT=22, WS=23;
	public static final String[] tokenNames = {
		"<INVALID>", "'<==>'", "'k+'", "']'", "'+'", "'['", "'products:'", "':'", 
		"'==>'", "'='", "'enzymes:'", "'K_m['", "';'", "'k_i['", "'{'", "']['", 
		"'}'", "'k-'", "ID", "ENZYME", "NUM", "VALUE", "COMMENT", "WS"
	};
	public static final int
		RULE_reactionset = 0, RULE_decl = 1, RULE_enzdecl = 2, RULE_reacdecl = 3, 
		RULE_iddecl = 4, RULE_matrix = 5, RULE_km = 6, RULE_ki = 7, RULE_enzval = 8, 
		RULE_reaction = 9, RULE_leftside = 10, RULE_rightside = 11, RULE_enzreaction = 12, 
		RULE_enzleftside = 13, RULE_enzrightside = 14, RULE_id = 15;
	public static final String[] ruleNames = {
		"reactionset", "decl", "enzdecl", "reacdecl", "iddecl", "matrix", "km", 
		"ki", "enzval", "reaction", "leftside", "rightside", "enzreaction", "enzleftside", 
		"enzrightside", "id"
	};

	@Override
	public String getGrammarFileName() { return "crn.g4"; }

	@Override
	public String[] getTokenNames() { return tokenNames; }

	@Override
	public String[] getRuleNames() { return ruleNames; }

	@Override
	public ATN getATN() { return _ATN; }

	public crnParser(TokenStream input) {
		super(input);
		_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
	}
	public static class ReactionsetContext extends ParserRuleContext {
		public ArrayList<Reaction> reactions = new ArrayList<Reaction>();
		public HashMap<String, Enzyme> enzymes = new HashMap<String, Enzyme>();
		public ArrayList<String> enzymenames = new ArrayList<String>();
		public ArrayList<String> symbols = new ArrayList<String>();
		public ArrayList<String> symbolList = new ArrayList<String>();
		public ArrayList<ArrayList<Double>> Kmvalues = new ArrayList<ArrayList<Double>>();
		public ArrayList<ArrayList<Double>> kivalues = new ArrayList<ArrayList<Double>>();
		public EnzreactionContext enzreaction(int i) {
			return getRuleContext(EnzreactionContext.class,i);
		}
		public ReactionContext reaction(int i) {
			return getRuleContext(ReactionContext.class,i);
		}
		public DeclContext decl() {
			return getRuleContext(DeclContext.class,0);
		}
		public List<ReactionContext> reaction() {
			return getRuleContexts(ReactionContext.class);
		}
		public List<EnzreactionContext> enzreaction() {
			return getRuleContexts(EnzreactionContext.class);
		}
		public MatrixContext matrix() {
			return getRuleContext(MatrixContext.class,0);
		}
		public ReactionsetContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_reactionset; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterReactionset(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitReactionset(this);
		}
	}

	public final ReactionsetContext reactionset() throws RecognitionException {
		ReactionsetContext _localctx = new ReactionsetContext(_ctx, getState());
		enterRule(_localctx, 0, RULE_reactionset);
		int _la;
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(32); decl();
			setState(33); matrix();
			setState(38); 
			_errHandler.sync(this);
			_la = _input.LA(1);
			do {
				{
				{
				setState(36);
				switch ( getInterpreter().adaptivePredict(_input,0,_ctx) ) {
				case 1:
					{
					setState(34); reaction();
					}
					break;

				case 2:
					{
					setState(35); enzreaction();
					}
					break;
				}
				}
				}
				setState(40); 
				_errHandler.sync(this);
				_la = _input.LA(1);
			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << 1) | (1L << ID) | (1L << ENZYME))) != 0) );
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class DeclContext extends ParserRuleContext {
		public ReacdeclContext reacdecl() {
			return getRuleContext(ReacdeclContext.class,0);
		}
		public EnzdeclContext enzdecl() {
			return getRuleContext(EnzdeclContext.class,0);
		}
		public DeclContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_decl; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterDecl(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitDecl(this);
		}
	}

	public final DeclContext decl() throws RecognitionException {
		DeclContext _localctx = new DeclContext(_ctx, getState());
		enterRule(_localctx, 2, RULE_decl);
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(42); enzdecl();
			setState(43); reacdecl();
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class EnzdeclContext extends ParserRuleContext {
		public Token ENZYME;
		public List<Token> e = new ArrayList<Token>();
		public List<TerminalNode> ENZYME() { return getTokens(crnParser.ENZYME); }
		public TerminalNode ENZYME(int i) {
			return getToken(crnParser.ENZYME, i);
		}
		public EnzdeclContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_enzdecl; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterEnzdecl(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitEnzdecl(this);
		}
	}

	public final EnzdeclContext enzdecl() throws RecognitionException {
		EnzdeclContext _localctx = new EnzdeclContext(_ctx, getState());
		enterRule(_localctx, 4, RULE_enzdecl);
		int _la;
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(45); match(10);
			setState(47); 
			_errHandler.sync(this);
			_la = _input.LA(1);
			do {
				{
				{
				setState(46); ((EnzdeclContext)_localctx).ENZYME = match(ENZYME);
				((EnzdeclContext)_localctx).e.add(((EnzdeclContext)_localctx).ENZYME);
				}
				}
				setState(49); 
				_errHandler.sync(this);
				_la = _input.LA(1);
			} while ( _la==ENZYME );
			}
			 for(int i = 0; i<((EnzdeclContext)_localctx).e.size(); i++) { 
						if(((EnzdeclContext)_localctx).e.get(i)!= null)
							((ReactionsetContext)getInvokingContext(0)).enzymes.put(((EnzdeclContext)_localctx).e.get(i).getText(), new Enzyme());
							((ReactionsetContext)getInvokingContext(0)).enzymenames.add(((EnzdeclContext)_localctx).e.get(i).getText());
					}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class ReacdeclContext extends ParserRuleContext {
		public List<IddeclContext> iddecl() {
			return getRuleContexts(IddeclContext.class);
		}
		public IddeclContext iddecl(int i) {
			return getRuleContext(IddeclContext.class,i);
		}
		public ReacdeclContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_reacdecl; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterReacdecl(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitReacdecl(this);
		}
	}

	public final ReacdeclContext reacdecl() throws RecognitionException {
		ReacdeclContext _localctx = new ReacdeclContext(_ctx, getState());
		enterRule(_localctx, 6, RULE_reacdecl);
		int _la;
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(51); match(6);
			setState(53); 
			_errHandler.sync(this);
			_la = _input.LA(1);
			do {
				{
				{
				setState(52); iddecl();
				}
				}
				setState(55); 
				_errHandler.sync(this);
				_la = _input.LA(1);
			} while ( _la==ID );
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class IddeclContext extends ParserRuleContext {
		public Token ID;
		public TerminalNode ID() { return getToken(crnParser.ID, 0); }
		public IddeclContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_iddecl; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterIddecl(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitIddecl(this);
		}
	}

	public final IddeclContext iddecl() throws RecognitionException {
		IddeclContext _localctx = new IddeclContext(_ctx, getState());
		enterRule(_localctx, 8, RULE_iddecl);
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(57); ((IddeclContext)_localctx).ID = match(ID);
			if ( !((ReactionsetContext)getInvokingContext(0)).symbolList.contains((((IddeclContext)_localctx).ID!=null?((IddeclContext)_localctx).ID.getText():null)) ) { ((ReactionsetContext)getInvokingContext(0)).symbolList.add((((IddeclContext)_localctx).ID!=null?((IddeclContext)_localctx).ID.getText():null)); } 
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class MatrixContext extends ParserRuleContext {
		public KmContext km() {
			return getRuleContext(KmContext.class,0);
		}
		public KiContext ki() {
			return getRuleContext(KiContext.class,0);
		}
		public MatrixContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_matrix; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterMatrix(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitMatrix(this);
		}
	}

	public final MatrixContext matrix() throws RecognitionException {
		MatrixContext _localctx = new MatrixContext(_ctx, getState());
		enterRule(_localctx, 10, RULE_matrix);
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(60); km();
			setState(61); ki();
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class KmContext extends ParserRuleContext {
		public EnzvalContext enzval;
		public List<EnzvalContext> enzlist = new ArrayList<EnzvalContext>();
		public List<EnzvalContext> enzval() {
			return getRuleContexts(EnzvalContext.class);
		}
		public EnzvalContext enzval(int i) {
			return getRuleContext(EnzvalContext.class,i);
		}
		public TerminalNode NUM(int i) {
			return getToken(crnParser.NUM, i);
		}
		public List<TerminalNode> NUM() { return getTokens(crnParser.NUM); }
		public KmContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_km; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterKm(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitKm(this);
		}
	}

	public final KmContext km() throws RecognitionException {
		KmContext _localctx = new KmContext(_ctx, getState());
		enterRule(_localctx, 12, RULE_km);
		int _la;
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(63); match(11);
			setState(64); match(NUM);
			setState(65); match(15);
			setState(66); match(NUM);
			setState(67); match(3);
			setState(68); match(7);
			setState(69); match(14);
			setState(71); 
			_errHandler.sync(this);
			_la = _input.LA(1);
			do {
				{
				{
				setState(70); ((KmContext)_localctx).enzval = enzval();
				((KmContext)_localctx).enzlist.add(((KmContext)_localctx).enzval);
				}
				}
				setState(73); 
				_errHandler.sync(this);
				_la = _input.LA(1);
			} while ( _la==14 );
			setState(75); match(16);
			}
			 for(int i = 0; i < ((KmContext)_localctx).enzlist.size(); i++)
						{
						  ((ReactionsetContext)getInvokingContext(0)).Kmvalues.add(((KmContext)_localctx).enzlist.get(i)!=null?((KmContext)_localctx).enzlist.get(i).values:null);
						}
					
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class KiContext extends ParserRuleContext {
		public EnzvalContext enzval;
		public List<EnzvalContext> enzlist = new ArrayList<EnzvalContext>();
		public List<EnzvalContext> enzval() {
			return getRuleContexts(EnzvalContext.class);
		}
		public EnzvalContext enzval(int i) {
			return getRuleContext(EnzvalContext.class,i);
		}
		public TerminalNode NUM(int i) {
			return getToken(crnParser.NUM, i);
		}
		public List<TerminalNode> NUM() { return getTokens(crnParser.NUM); }
		public KiContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_ki; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterKi(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitKi(this);
		}
	}

	public final KiContext ki() throws RecognitionException {
		KiContext _localctx = new KiContext(_ctx, getState());
		enterRule(_localctx, 14, RULE_ki);
		int _la;
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(77); match(13);
			setState(78); match(NUM);
			setState(79); match(15);
			setState(80); match(NUM);
			setState(81); match(3);
			setState(82); match(7);
			setState(83); match(14);
			setState(85); 
			_errHandler.sync(this);
			_la = _input.LA(1);
			do {
				{
				{
				setState(84); ((KiContext)_localctx).enzval = enzval();
				((KiContext)_localctx).enzlist.add(((KiContext)_localctx).enzval);
				}
				}
				setState(87); 
				_errHandler.sync(this);
				_la = _input.LA(1);
			} while ( _la==14 );
			setState(89); match(16);
			}
			 for(int i = 0; i < ((KiContext)_localctx).enzlist.size(); i++)
						{
						  ((ReactionsetContext)getInvokingContext(0)).kivalues.add(((KiContext)_localctx).enzlist.get(i)!=null?((KiContext)_localctx).enzlist.get(i).values:null);
						}
					
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class EnzvalContext extends ParserRuleContext {
		public ArrayList<Double> values = new ArrayList<Double>();
		public Token VALUE;
		public List<Token> el = new ArrayList<Token>();
		public List<TerminalNode> VALUE() { return getTokens(crnParser.VALUE); }
		public TerminalNode VALUE(int i) {
			return getToken(crnParser.VALUE, i);
		}
		public EnzvalContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_enzval; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterEnzval(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitEnzval(this);
		}
	}

	public final EnzvalContext enzval() throws RecognitionException {
		EnzvalContext _localctx = new EnzvalContext(_ctx, getState());
		enterRule(_localctx, 16, RULE_enzval);
		int _la;
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(91); match(14);
			setState(93); 
			_errHandler.sync(this);
			_la = _input.LA(1);
			do {
				{
				{
				setState(92); ((EnzvalContext)_localctx).VALUE = match(VALUE);
				((EnzvalContext)_localctx).el.add(((EnzvalContext)_localctx).VALUE);
				}
				}
				setState(95); 
				_errHandler.sync(this);
				_la = _input.LA(1);
			} while ( _la==VALUE );
			setState(97); match(16);
			}
			 
						
						for(int i = 0; i < ((EnzvalContext)_localctx).el.size(); i++)
							{
						  	((EnzvalContext)getInvokingContext(8)).values.add( (((EnzvalContext)_localctx).el.get(i)!=null?Double.parseDouble(((EnzvalContext)_localctx).el.get(i).getText()):null) );
							}
					
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class ReactionContext extends ParserRuleContext {
		public ArrayList<String> reactants = new ArrayList<String>();
		public ArrayList<String> products = new ArrayList<String>();
		public Token v1;
		public Token v2;
		public List<TerminalNode> VALUE() { return getTokens(crnParser.VALUE); }
		public RightsideContext rightside() {
			return getRuleContext(RightsideContext.class,0);
		}
		public TerminalNode VALUE(int i) {
			return getToken(crnParser.VALUE, i);
		}
		public LeftsideContext leftside() {
			return getRuleContext(LeftsideContext.class,0);
		}
		public ReactionContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_reaction; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterReaction(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitReaction(this);
		}
	}

	public final ReactionContext reaction() throws RecognitionException {
		ReactionContext _localctx = new ReactionContext(_ctx, getState());
		enterRule(_localctx, 18, RULE_reaction);
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(99); leftside();
			setState(100); match(1);
			setState(101); rightside();
			setState(102); match(5);
			setState(103); match(2);
			setState(104); match(9);
			setState(105); ((ReactionContext)_localctx).v1 = match(VALUE);
			setState(106); match(12);
			setState(107); match(17);
			setState(108); match(9);
			setState(109); ((ReactionContext)_localctx).v2 = match(VALUE);
			setState(110); match(3);
			}
			 ((ReactionsetContext)getInvokingContext(0)).reactions.add(new Reaction(_localctx.reactants,_localctx.products,Double.parseDouble((((ReactionContext)_localctx).v1!=null?((ReactionContext)_localctx).v1.getText():null)), Double.parseDouble((((ReactionContext)_localctx).v2!=null?((ReactionContext)_localctx).v2.getText():null)))); 
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class LeftsideContext extends ParserRuleContext {
		public IdContext id;
		public IdContext i1;
		public IdContext i2;
		public List<IdContext> id() {
			return getRuleContexts(IdContext.class);
		}
		public IdContext id(int i) {
			return getRuleContext(IdContext.class,i);
		}
		public LeftsideContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_leftside; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterLeftside(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitLeftside(this);
		}
	}

	public final LeftsideContext leftside() throws RecognitionException {
		LeftsideContext _localctx = new LeftsideContext(_ctx, getState());
		enterRule(_localctx, 20, RULE_leftside);
		try {
			setState(121);
			switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) {
			case 1:
				enterOuterAlt(_localctx, 1);
				{
				}
				break;

			case 2:
				enterOuterAlt(_localctx, 2);
				{
				setState(113); ((LeftsideContext)_localctx).id = id();
				((ReactionContext)getInvokingContext(9)).reactants.add((((LeftsideContext)_localctx).id!=null?_input.getText(((LeftsideContext)_localctx).id.start,((LeftsideContext)_localctx).id.stop):null));
				}
				break;

			case 3:
				enterOuterAlt(_localctx, 3);
				{
				setState(116); ((LeftsideContext)_localctx).i1 = id();
				setState(117); match(4);
				setState(118); ((LeftsideContext)_localctx).i2 = id();
				((ReactionContext)getInvokingContext(9)).reactants.add((((LeftsideContext)_localctx).i1!=null?_input.getText(((LeftsideContext)_localctx).i1.start,((LeftsideContext)_localctx).i1.stop):null));((ReactionContext)getInvokingContext(9)).reactants.add((((LeftsideContext)_localctx).i2!=null?_input.getText(((LeftsideContext)_localctx).i2.start,((LeftsideContext)_localctx).i2.stop):null));
				}
				break;
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class RightsideContext extends ParserRuleContext {
		public IdContext id;
		public IdContext i1;
		public IdContext i2;
		public List<IdContext> id() {
			return getRuleContexts(IdContext.class);
		}
		public IdContext id(int i) {
			return getRuleContext(IdContext.class,i);
		}
		public RightsideContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_rightside; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterRightside(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitRightside(this);
		}
	}

	public final RightsideContext rightside() throws RecognitionException {
		RightsideContext _localctx = new RightsideContext(_ctx, getState());
		enterRule(_localctx, 22, RULE_rightside);
		try {
			setState(132);
			switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) {
			case 1:
				enterOuterAlt(_localctx, 1);
				{
				}
				break;

			case 2:
				enterOuterAlt(_localctx, 2);
				{
				setState(124); ((RightsideContext)_localctx).id = id();
				((ReactionContext)getInvokingContext(9)).products.add((((RightsideContext)_localctx).id!=null?_input.getText(((RightsideContext)_localctx).id.start,((RightsideContext)_localctx).id.stop):null));
				}
				break;

			case 3:
				enterOuterAlt(_localctx, 3);
				{
				setState(127); ((RightsideContext)_localctx).i1 = id();
				setState(128); match(4);
				setState(129); ((RightsideContext)_localctx).i2 = id();
				((ReactionContext)getInvokingContext(9)).products.add((((RightsideContext)_localctx).i1!=null?_input.getText(((RightsideContext)_localctx).i1.start,((RightsideContext)_localctx).i1.stop):null));((ReactionContext)getInvokingContext(9)).products.add((((RightsideContext)_localctx).i2!=null?_input.getText(((RightsideContext)_localctx).i2.start,((RightsideContext)_localctx).i2.stop):null));
				}
				break;
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class EnzreactionContext extends ParserRuleContext {
		public String reactants = "";
		public String enzyme = "";
		public String enzleft = "";
		public String enzright = "";
		public ArrayList<String> products = new ArrayList<String>();
		public EnzleftsideContext enzleftside() {
			return getRuleContext(EnzleftsideContext.class,0);
		}
		public EnzrightsideContext enzrightside() {
			return getRuleContext(EnzrightsideContext.class,0);
		}
		public EnzreactionContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_enzreaction; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterEnzreaction(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitEnzreaction(this);
		}
	}

	public final EnzreactionContext enzreaction() throws RecognitionException {
		EnzreactionContext _localctx = new EnzreactionContext(_ctx, getState());
		enterRule(_localctx, 24, RULE_enzreaction);
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(134); enzleftside();
			setState(135); match(8);
			setState(136); enzrightside();
			}

				if(_localctx.enzleft.equals(_localctx.enzright)){
					((EnzreactionContext)_localctx).enzyme =  _localctx.enzleft;
			 		((ReactionsetContext)getInvokingContext(0)).reactions.add(new EnzymaticReaction(_localctx.reactants,_localctx.enzyme,_localctx.products)); 
					Enzyme myEnz;
					if(((ReactionsetContext)getInvokingContext(0)).enzymes.containsKey(_localctx.enzyme)){
						myEnz = ((ReactionsetContext)getInvokingContext(0)).enzymes.get(_localctx.enzyme);
					} else {
						myEnz = new Enzyme();
						((ReactionsetContext)getInvokingContext(0)).enzymes.put(_localctx.enzyme,myEnz);
						System.err.println("WARNING: unknown enzyme");
					}
					if(!myEnz.Kms.containsKey(_localctx.reactants)){
						myEnz.Kms.put(_localctx.reactants,((ReactionsetContext)getInvokingContext(0)).Kmvalues.get(((ReactionsetContext)getInvokingContext(0)).enzymenames.indexOf(_localctx.enzyme)).get(((ReactionsetContext)getInvokingContext(0)).symbolList.indexOf(_localctx.reactants)));
						myEnz.kis.put(_localctx.reactants,((ReactionsetContext)getInvokingContext(0)).kivalues.get(((ReactionsetContext)getInvokingContext(0)).enzymenames.indexOf(_localctx.enzyme)).get(((ReactionsetContext)getInvokingContext(0)).symbolList.indexOf(_localctx.reactants)));
					}
				} else {
					System.err.println("Enzyme mismatch: "+_localctx.enzleft+" "+_localctx.enzright);
				}

		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class EnzleftsideContext extends ParserRuleContext {
		public IdContext id;
		public Token ENZYME;
		public IdContext id() {
			return getRuleContext(IdContext.class,0);
		}
		public TerminalNode ENZYME() { return getToken(crnParser.ENZYME, 0); }
		public EnzleftsideContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_enzleftside; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterEnzleftside(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitEnzleftside(this);
		}
	}

	public final EnzleftsideContext enzleftside() throws RecognitionException {
		EnzleftsideContext _localctx = new EnzleftsideContext(_ctx, getState());
		enterRule(_localctx, 26, RULE_enzleftside);
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(145);
			switch (_input.LA(1)) {
			case ID:
				{
				setState(138); ((EnzleftsideContext)_localctx).id = id();
				setState(139); match(4);
				setState(140); ((EnzleftsideContext)_localctx).ENZYME = match(ENZYME);
				}
				break;
			case ENZYME:
				{
				setState(142); ((EnzleftsideContext)_localctx).ENZYME = match(ENZYME);
				setState(143); match(4);
				setState(144); ((EnzleftsideContext)_localctx).id = id();
				}
				break;
			default:
				throw new NoViableAltException(this);
			}
			((EnzreactionContext)getInvokingContext(12)).enzleft =  (((EnzleftsideContext)_localctx).ENZYME!=null?((EnzleftsideContext)_localctx).ENZYME.getText():null);((EnzreactionContext)getInvokingContext(12)).reactants =  (((EnzleftsideContext)_localctx).id!=null?_input.getText(((EnzleftsideContext)_localctx).id.start,((EnzleftsideContext)_localctx).id.stop):null);
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class EnzrightsideContext extends ParserRuleContext {
		public Token ENZYME;
		public IdContext id;
		public IdContext p1;
		public IdContext p2;
		public List<IdContext> id() {
			return getRuleContexts(IdContext.class);
		}
		public TerminalNode ENZYME() { return getToken(crnParser.ENZYME, 0); }
		public IdContext id(int i) {
			return getRuleContext(IdContext.class,i);
		}
		public EnzrightsideContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_enzrightside; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterEnzrightside(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitEnzrightside(this);
		}
	}

	public final EnzrightsideContext enzrightside() throws RecognitionException {
		EnzrightsideContext _localctx = new EnzrightsideContext(_ctx, getState());
		enterRule(_localctx, 28, RULE_enzrightside);
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(162);
			switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) {
			case 1:
				{
				setState(149); ((EnzrightsideContext)_localctx).ENZYME = match(ENZYME);
				}
				break;

			case 2:
				{
				setState(150); ((EnzrightsideContext)_localctx).ENZYME = match(ENZYME);
				setState(151); match(4);
				setState(152); ((EnzrightsideContext)_localctx).id = id();
				((EnzreactionContext)getInvokingContext(12)).products.add((((EnzrightsideContext)_localctx).id!=null?_input.getText(((EnzrightsideContext)_localctx).id.start,((EnzrightsideContext)_localctx).id.stop):null));
				}
				break;

			case 3:
				{
				setState(155); ((EnzrightsideContext)_localctx).ENZYME = match(ENZYME);
				setState(156); match(4);
				setState(157); ((EnzrightsideContext)_localctx).p1 = ((EnzrightsideContext)_localctx).id = id();
				setState(158); match(4);
				setState(159); ((EnzrightsideContext)_localctx).p2 = ((EnzrightsideContext)_localctx).id = id();
				((EnzreactionContext)getInvokingContext(12)).products.add((((EnzrightsideContext)_localctx).p1!=null?_input.getText(((EnzrightsideContext)_localctx).p1.start,((EnzrightsideContext)_localctx).p1.stop):null));((EnzreactionContext)getInvokingContext(12)).products.add((((EnzrightsideContext)_localctx).p2!=null?_input.getText(((EnzrightsideContext)_localctx).p2.start,((EnzrightsideContext)_localctx).p2.stop):null));
				}
				break;
			}
			((EnzreactionContext)getInvokingContext(12)).enzright =  (((EnzrightsideContext)_localctx).ENZYME!=null?((EnzrightsideContext)_localctx).ENZYME.getText():null);
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static class IdContext extends ParserRuleContext {
		public Token ID;
		public TerminalNode ID() { return getToken(crnParser.ID, 0); }
		public IdContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_id; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).enterId(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof crnListener ) ((crnListener)listener).exitId(this);
		}
	}

	public final IdContext id() throws RecognitionException {
		IdContext _localctx = new IdContext(_ctx, getState());
		enterRule(_localctx, 30, RULE_id);
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(166); ((IdContext)_localctx).ID = match(ID);
			if ( !((ReactionsetContext)getInvokingContext(0)).symbols.contains((((IdContext)_localctx).ID!=null?((IdContext)_localctx).ID.getText():null)) ) { ((ReactionsetContext)getInvokingContext(0)).symbols.add((((IdContext)_localctx).ID!=null?((IdContext)_localctx).ID.getText():null)); } 
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

	public static final String _serializedATN =
		"\3\uacf5\uee8c\u4f5d\u8b0d\u4a45\u78bd\u1b2f\u3378\3\31\u00ac\4\2\t\2"+
		"\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
		"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\3\2\3\2"+
		"\3\2\3\2\5\2\'\n\2\6\2)\n\2\r\2\16\2*\3\3\3\3\3\3\3\4\3\4\6\4\62\n\4\r"+
		"\4\16\4\63\3\5\3\5\6\58\n\5\r\5\16\59\3\6\3\6\3\6\3\7\3\7\3\7\3\b\3\b"+
		"\3\b\3\b\3\b\3\b\3\b\3\b\6\bJ\n\b\r\b\16\bK\3\b\3\b\3\t\3\t\3\t\3\t\3"+
		"\t\3\t\3\t\3\t\6\tX\n\t\r\t\16\tY\3\t\3\t\3\n\3\n\6\n`\n\n\r\n\16\na\3"+
		"\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13"+
		"\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\5\f|\n\f\3\r\3\r\3\r\3\r\3\r\3\r"+
		"\3\r\3\r\3\r\5\r\u0087\n\r\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17"+
		"\3\17\3\17\5\17\u0094\n\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+
		"\3\20\3\20\3\20\3\20\3\20\3\20\5\20\u00a5\n\20\3\20\3\20\3\21\3\21\3\21"+
		"\3\21\2\22\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \2\2\u00a9\2\"\3\2\2"+
		"\2\4,\3\2\2\2\6/\3\2\2\2\b\65\3\2\2\2\n;\3\2\2\2\f>\3\2\2\2\16A\3\2\2"+
		"\2\20O\3\2\2\2\22]\3\2\2\2\24e\3\2\2\2\26{\3\2\2\2\30\u0086\3\2\2\2\32"+
		"\u0088\3\2\2\2\34\u0093\3\2\2\2\36\u00a4\3\2\2\2 \u00a8\3\2\2\2\"#\5\4"+
		"\3\2#(\5\f\7\2$\'\5\24\13\2%\'\5\32\16\2&$\3\2\2\2&%\3\2\2\2\')\3\2\2"+
		"\2(&\3\2\2\2)*\3\2\2\2*(\3\2\2\2*+\3\2\2\2+\3\3\2\2\2,-\5\6\4\2-.\5\b"+
		"\5\2.\5\3\2\2\2/\61\7\f\2\2\60\62\7\25\2\2\61\60\3\2\2\2\62\63\3\2\2\2"+
		"\63\61\3\2\2\2\63\64\3\2\2\2\64\7\3\2\2\2\65\67\7\b\2\2\668\5\n\6\2\67"+
		"\66\3\2\2\289\3\2\2\29\67\3\2\2\29:\3\2\2\2:\t\3\2\2\2;<\7\24\2\2<=\b"+
		"\6\1\2=\13\3\2\2\2>?\5\16\b\2?@\5\20\t\2@\r\3\2\2\2AB\7\r\2\2BC\7\26\2"+
		"\2CD\7\21\2\2DE\7\26\2\2EF\7\5\2\2FG\7\t\2\2GI\7\20\2\2HJ\5\22\n\2IH\3"+
		"\2\2\2JK\3\2\2\2KI\3\2\2\2KL\3\2\2\2LM\3\2\2\2MN\7\22\2\2N\17\3\2\2\2"+
		"OP\7\17\2\2PQ\7\26\2\2QR\7\21\2\2RS\7\26\2\2ST\7\5\2\2TU\7\t\2\2UW\7\20"+
		"\2\2VX\5\22\n\2WV\3\2\2\2XY\3\2\2\2YW\3\2\2\2YZ\3\2\2\2Z[\3\2\2\2[\\\7"+
		"\22\2\2\\\21\3\2\2\2]_\7\20\2\2^`\7\27\2\2_^\3\2\2\2`a\3\2\2\2a_\3\2\2"+
		"\2ab\3\2\2\2bc\3\2\2\2cd\7\22\2\2d\23\3\2\2\2ef\5\26\f\2fg\7\3\2\2gh\5"+
		"\30\r\2hi\7\7\2\2ij\7\4\2\2jk\7\13\2\2kl\7\27\2\2lm\7\16\2\2mn\7\23\2"+
		"\2no\7\13\2\2op\7\27\2\2pq\7\5\2\2q\25\3\2\2\2r|\3\2\2\2st\5 \21\2tu\b"+
		"\f\1\2u|\3\2\2\2vw\5 \21\2wx\7\6\2\2xy\5 \21\2yz\b\f\1\2z|\3\2\2\2{r\3"+
		"\2\2\2{s\3\2\2\2{v\3\2\2\2|\27\3\2\2\2}\u0087\3\2\2\2~\177\5 \21\2\177"+
		"\u0080\b\r\1\2\u0080\u0087\3\2\2\2\u0081\u0082\5 \21\2\u0082\u0083\7\6"+
		"\2\2\u0083\u0084\5 \21\2\u0084\u0085\b\r\1\2\u0085\u0087\3\2\2\2\u0086"+
		"}\3\2\2\2\u0086~\3\2\2\2\u0086\u0081\3\2\2\2\u0087\31\3\2\2\2\u0088\u0089"+
		"\5\34\17\2\u0089\u008a\7\n\2\2\u008a\u008b\5\36\20\2\u008b\33\3\2\2\2"+
		"\u008c\u008d\5 \21\2\u008d\u008e\7\6\2\2\u008e\u008f\7\25\2\2\u008f\u0094"+
		"\3\2\2\2\u0090\u0091\7\25\2\2\u0091\u0092\7\6\2\2\u0092\u0094\5 \21\2"+
		"\u0093\u008c\3\2\2\2\u0093\u0090\3\2\2\2\u0094\u0095\3\2\2\2\u0095\u0096"+
		"\b\17\1\2\u0096\35\3\2\2\2\u0097\u00a5\7\25\2\2\u0098\u0099\7\25\2\2\u0099"+
		"\u009a\7\6\2\2\u009a\u009b\5 \21\2\u009b\u009c\b\20\1\2\u009c\u00a5\3"+
		"\2\2\2\u009d\u009e\7\25\2\2\u009e\u009f\7\6\2\2\u009f\u00a0\5 \21\2\u00a0"+
		"\u00a1\7\6\2\2\u00a1\u00a2\5 \21\2\u00a2\u00a3\b\20\1\2\u00a3\u00a5\3"+
		"\2\2\2\u00a4\u0097\3\2\2\2\u00a4\u0098\3\2\2\2\u00a4\u009d\3\2\2\2\u00a5"+
		"\u00a6\3\2\2\2\u00a6\u00a7\b\20\1\2\u00a7\37\3\2\2\2\u00a8\u00a9\7\24"+
		"\2\2\u00a9\u00aa\b\21\1\2\u00aa!\3\2\2\2\r&*\639KYa{\u0086\u0093\u00a4";
	public static final ATN _ATN =
		ATNSimulator.deserialize(_serializedATN.toCharArray());
	static {
		_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
		for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
			_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
		}
	}
}